<template>
  <div class="overview-common">
    <px-empty v-if="type === 'empty'" style="padding-top: 150px" description="暂时没有数据">
      <p class="overview-tips">请添加您关注的看板或指标</p>
      <px-button type="primary" icon="Plus" @click="handleAddEmpty">立即添加</px-button>
    </px-empty>
    <div v-if="type === 'edit'" class="fixed-button">
      <px-button type="primary" icon="software" @click="handleAddComp">添加组件</px-button>
      <px-button type="primary" plain icon="CloseCircle" @click="handleClear">清空</px-button>
      <px-button type="primary" icon="ValidationHistory" @click="handleSave">保存</px-button>
      <px-button plain type="primary" icon="CloseCircle" @click="handlePageCancel">取消</px-button>
    </div>
    <div v-if="type === 'view'" class="fixed-button">
      <px-button type="primary" icon="Setting" @click="handleSetting">看板设置</px-button>
    </div>
    <px-scrollbar v-if="type === 'edit'" height=" calc(100vh - 120px)">
      <!-- 添加或修改参数配置对话框 -->
      <px-dialog v-model="visible" :close-on-click-modal="false" title="添加组件" width="800px" destroy-on-close append-to-body @close="handleCancel">
        <px-form :ref="boardRef" :model="formValue" label-width="80px">
          <px-form-item label="所属菜单" prop="resourceId">
            <px-select
              v-model="formValue.resourceId"
              clearable
              filterable
              placeholder="请选择所属菜单"
              style="width: 100%"
              @change="getFilterChartList"
            >
              <px-option v-for="item in menuTreeData" :key="item.resourceId" :label="item.title" :value="item.resourceId" />
            </px-select>
          </px-form-item>
          <px-form-item label="能源类型" prop="energyType">
            <px-select v-model="formValue.energyType" filterable clearable style="width: 100%" @change="getFilterChartList">
              <px-option v-for="item in energyTypeList" :key="item.value" :label="item.name" :value="item.value" />
            </px-select>
          </px-form-item>
          <px-form-item label="系统" prop="systemCode">
            <px-cascader
              ref="systemRef"
              v-model="formValue.systemCode"
              filterable
              clearable
              style="width: 100%"
              :options="systemList"
              :props="systemProps"
              placeholder="请选择系统"
              @change="handleChangeSystem"
            />
          </px-form-item>
          <px-scrollbar height="400px">
            <px-text>
              <px-icon color="orange">
                <InfoCircleFilled />
              </px-icon>
              看板区域按照宽高比例划分为4*3共12个单元格，每个组件具有预设大小
            </px-text>
            <px-checkbox-group v-model="activeChart" class="chart-list" size="small">
              <px-checkbox-button v-for="item in filterChartList" :key="item.componentNumber" :label="item">
                <px-text size="large" tag="b">
                  <px-icon size="20" color="#3b82f6" style="margin-right: 10px"><Histogram /></px-icon>{{ item.componentName }}
                </px-text>
                <img :src="imgList[item.componentType]" />
                <p>{{ item.width }} * {{ item.length }}</p>
              </px-checkbox-button>
            </px-checkbox-group>
          </px-scrollbar>
        </px-form>
        <template #footer>
          <div class="dialog-footer">
            <px-button @click="handleCancel">取 消</px-button>
            <px-button type="primary" @click="handleSubmit">确 定</px-button>
          </div>
        </template>
      </px-dialog>
      <grid-layout
        v-if="type === 'edit'"
        v-model:layout="tempChartList"
        :col-num="4"
        :row-height="232"
        is-draggable
        is-resizable
        vertical-compact
        use-css-transforms
        @layout-updated="handleUpdated"
      >
        <grid-item
          v-for="(item, index) in tempChartList"
          :key="item.componentNumber"
          :x="item.x"
          :y="item.y"
          :w="item.w"
          :h="item.h"
          :i="item.componentNumber"
          :minW="item.width"
          :minH="item.length"
          :preserve-aspect-ratio="true"
        >
          <px-card shadow="never" style="height: 100%" class="box-card">
            <template #header>
              <div class="card-header">
                <div class="card-title">
                  <span> {{ item.componentName }}</span>
                </div>
                <px-tooltip content="删除" placement="top">
                  <px-button class="button" type="danger" link icon="Delete" @click="handleDelete(index)" />
                </px-tooltip>
              </div>
            </template>
            <img class="card-content" :src="imgList[item.componentType]" />
          </px-card>
        </grid-item>
      </grid-layout>
    </px-scrollbar>
    <px-scrollbar
      v-if="type === 'view'"
      v-loading="componentLoading"
      element-loading-background="rgba(122, 122, 122, 0.8)"
      element-loading-text="组件努力加载中，请稍候..."
    >
      <grid-layout
        v-model:layout="chartList"
        :col-num="4"
        :row-height="232"
        :is-draggable="false"
        :is-resizable="false"
        vertical-compact
        use-css-transforms
      >
        <grid-item
          v-for="item in chartList"
          :key="item.componentNumber"
          :x="item.x"
          :y="item.y"
          :w="item.w"
          :h="item.h"
          :i="item.componentNumber"
          :minW="item.width"
          :minH="item.length"
        >
          <component :is="item.components" :key="item.componentNumber" />
        </grid-item>
      </grid-layout>
    </px-scrollbar>
  </div>
</template>

<script lang="ts" setup>
import { queryDictData } from "@/api/common";
import { querySystemSelect } from "@/api/equip/archive";
import { addChartData, getChartList, getFilterMenuData, getFilterTableData, updateChartData } from "@/api/system/board";
import DATA from "@/assets/images/bench/DATA.png";
import HISTOGRAM from "@/assets/images/bench/HISTOGRAM.png";
import LINE_CHART from "@/assets/images/bench/LINE_CHART.png";
import METER from "@/assets/images/bench/METER.png";
import PIE_CHART from "@/assets/images/bench/PIE_CHART.png";
import { GridItem, GridLayout } from "grid-layout-plus";
import { PxMessage, PxMessageBox } from "px-ui";
import { markRaw, onMounted, reactive, ref, toRefs } from "vue";

const boardRef = ref("");

const componentLoading = ref(false);

const imgList = {
  PIE_CHART: PIE_CHART,
  LINE_CHART: LINE_CHART,
  DATA: DATA,
  HISTOGRAM: HISTOGRAM,
  METER: METER
};

const systemProps = {
  children: "children",
  label: "name",
  value: "code"
};

const data = reactive<Record<string, any>>({
  formValue: {},
  energyTypeList: [],
  menuTreeData: [],
  chartList: [],
  systemList: [],
  visible: false,
  activeChart: [],
  tempChartList: [], // 暂存选中的组件
  type: "",
  filterChartList: [],
  dynamicComponents: {},
  isEdit: false // 标记是更新还是新增自定义组件状态
});

const {
  formValue,
  energyTypeList,
  menuTreeData,
  activeChart,
  tempChartList,
  chartList,
  filterChartList,
  systemList,
  visible,
  type,
  dynamicComponents,
  isEdit
} = toRefs(data);

const generateComponent = async () => {
  const modulesWater = import.meta.glob("../../../../water/water/*.vue");
  const modulesWMachine = import.meta.glob("../../../../machine/components/*.vue");
  const modulesEle = import.meta.glob("../../../../electricity/components/*.vue");
  const moduleGas = import.meta.glob("../../../../gas/operation/overview/commonComponents/*.vue");
  const moduleOtherGas = import.meta.glob("../../../../gas/operation/overview/components/*.vue");
  const moduleEnergy = import.meta.glob("../../../../common/energy/components/*.vue");
  const modules = { ...modulesEle, ...modulesWMachine, ...modulesWater, ...moduleGas, ...moduleOtherGas, ...moduleEnergy };
  for (const path in modules) {
    const module = await modules[path]();
    const componentName = path.replace(/^.+\/(.*).vue$/, "$1");
    for (const item of chartList.value) {
      if (item.urlAddress === componentName) {
        const index = chartList.value?.findIndex(item => componentName === item.urlAddress);
        chartList.value.splice(index, 1, { ...item, components: markRaw(module.default) });
      }
    }
  }
};

const handleGetDictData = async () => {
  energyTypeList.value = await queryDictData({ typeCode: "ENERGY" });
  menuTreeData.value = await getFilterMenuData();
  systemList.value = await querySystemSelect({ factoryArea: "", className: "" });
};

// 点击空页面的立即添加
const handleAddEmpty = () => {
  type.value = "edit";
  isEdit.value = false;
  dynamicComponents.value = {};
  tempChartList.value = [];
  handleAddComp();
};
const handleUpdated = newLayout => {
  tempChartList.value = newLayout;
};

// 获取用户已经添加的组件的列表
const getChart = async () => {
  componentLoading.value = true;
  dynamicComponents.value = {};
  const res = (await getChartList()) || [];
  if (res?.length === 0) {
    type.value = "empty";
    isEdit.value = false;
    return;
  }
  type.value = "view";
  const arr = [];
  res?.forEach(item => {
    arr.push({
      x: item.coordinateX,
      y: item.coordinateY,
      w: item.width,
      h: item.length,
      i: item.componentNumber,
      ...item
    });
  });
  chartList.value = arr;
  await generateComponent();
  componentLoading.value = false;
};

onMounted(async () => {
  componentLoading.value = true;
  await handleGetDictData();
  await getChart();
  if (chartList.value?.length === 0) {
    type.value = "empty";
  } else {
    type.value = "view";
  }
});

const handleSetting = () => {
  type.value = "edit";
  isEdit.value = true;
  const arr = [];
  chartList.value.forEach(item => {
    arr.push({
      x: item.coordinateX,
      y: item.coordinateY,
      w: item.width,
      h: item.length,
      i: item.componentNumber,
      ...item
    });
  });
  tempChartList.value = arr;
};

const handleDelete = index => {
  tempChartList.value.splice(index, 1);
};

// 弹窗添加组件-这里需要做一个去重
const handleSubmit = () => {
  const temp = [];
  if (activeChart.value?.length !== 0) {
    activeChart.value?.forEach((item, index) => {
      temp.push({ ...item, x: 0, y: tempChartList.value.length + index + 1, w: item.width, h: item.length, i: item.componentNumber });
    });
    tempChartList.value = tempChartList.value?.concat(temp)?.filter((obj, index, self) => {
      return self.map(x => x.componentNumber).indexOf(obj.componentNumber) === index;
    });
  }
  handleCancel();
};
// 弹窗添加组件 -- 取消
const handleCancel = () => {
  activeChart.value = [];
  visible.value = false;
};

// 修改系统时候，后端需要拿到最后一级的code
const handleChangeSystem = val => {
  if (val) {
    formValue.value.systemCode = val[val?.length - 1];
  }
  getFilterChartList();
};

// 获取有权限的菜单下的所有组件列表
const getFilterChartList = async () => {
  filterChartList.value = await getFilterTableData({ ...formValue.value });
};

// 点击添加组件
const handleAddComp = async () => {
  await getFilterChartList();
  visible.value = true;
};

const handleClear = () => {
  PxMessageBox.confirm(`确定要清空所有已添加的组件吗？`, "提示", {
    confirmButtonText: "确定",
    confirmButtonClass: "px-button--danger",
    cancelButtonText: "取消",
    type: "warning",
    draggable: true
  })
    .then(async () => {
      tempChartList.value = [];
      PxMessage.success("清空成功");
    })
    .catch(() => {});
};

// 整个添加页面的保存
const handleSave = async () => {
  let arr = [];
  tempChartList.value?.forEach(item => {
    arr.push({ ...item, coordinateX: item.x, coordinateY: item.y, width: item.w, length: item.h });
  });
  const res = isEdit.value ? await updateChartData(arr) : await addChartData(arr);
  if (res) {
    getChart();
  }
};

const handlePageCancel = () => {
  if (isEdit.value) {
    type.value = "view";
  } else {
    type.value = "empty";
  }
};
</script>

<style lang="scss" scoped>
.overview-common {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  height: calc(100vh - 180px);
  // background-color: #fff;
  border-radius: 5px;

  .overview-tips {
    margin-bottom: 10px;
    font-size: 14px;
    color: #000;
  }

  .fixed-button {
    position: absolute;
    top: -46px;
    right: 0;
  }
}

.chart-list {
  // margin: 0 auto;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  width: 100%;

  label {
    box-sizing: border-box;
    width: 220px;
    margin: 12px;

    span {
      // width: 220px;
      // border-radius: 5px;
      // border: 1px solid #eee;
      img {
        width: 30px;
        height: 30px;
      }
    }
  }
}

:deep(.px-checkbox-button__inner) {
  border: none;
}

:deep(.px-card__header) {
  border: none;
}

:deep(.px-checkbox-button:first-child .px-checkbox-button__inner) {
  border: none;
}

:deep(.px-checkbox-button--small .px-checkbox-button__inner) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  width: 220px;
  height: 140px;
  margin: 12px;
  background-color: #e3e8f1;
  border-radius: 5px;
}

:deep(.px-checkbox-button.is-checked .px-checkbox-button__inner) {
  --px-checkbox-button-checked-text-color: #666;

  border: 1px solid #3b82f6;
}

.box-card {
  height: 100%;

  .card-content {
    width: 64px;
    height: 64px;
  }

  .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .card-title {
      display: flex;
      gap: 24px;
      align-items: center;
      justify-content: space-between;
      width: 100%;
      height: 32px;
      background: linear-gradient(270deg, rgb(59 130 246 / 0%) 0%, rgb(59 130 246 / 24%) 100%) no-repeat;
      background-size: 280px;
      border-left: 4px solid var(--px-color-primary);

      span {
        font-size: 18px;
        font-weight: 600;
        line-height: 1;
        color: #333;
        text-indent: 8px;
        white-space: nowrap;
        user-select: none;
      }
    }
  }

  :deep(.px-card__body) {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    height: calc(100% - 50px);
    padding: 0 20px !important;
  }
}
</style>
